#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <vector>

#include <sw/redis++/redis++.h>

#include "util.hpp"

using std::cout;
using std::endl;
using std::string;

namespace redis = sw::redis;

// 测试字符串的 set 和 get
void test_get_and_set(redis::Redis &redis){

    // 先清空数据库
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");

    // 因为 get 返回的是 Optional 类型，首先需要取其中的value
    // 其次如果没有数据，使用会抛异常，需要先判断，optional 可以隐式转化为 bool
    auto value1 = redis.get("key1");
    if(value1){
        cout << "value1: " << value1.value() << endl;
    }
    auto value2 = redis.get("key2");
    if(value2){
        cout << "value2: " << value2.value() << endl;
    }
    auto value3 = redis.get("key3");
    if(value3){
        cout << "value3: " << value3.value() << endl;
    }
    auto value4 = redis.get("key4");
    if(value4){
        cout << "value4: " << value4.value() << endl;
    }
    else{
        cout << "key4 不存在" << endl;
    }
}

// 测试 exists 和 del
void test_exists_and_del(redis::Redis &redis){
    cout << "test exists and del" << endl;
    // 先清空数据库
    redis.flushall();

    // 设置值
    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");

    // 判断值是否存在 —— 返回值是存在的 key 的个数
    auto res = redis.exists("key1");
    cout << "key1 是否存在: " << res << endl;

    // 可以判断多个，使用初始化列表
    res = redis.exists({"key1", "key3", "key4"});
    cout << res << endl;

    // 删除，同样支持删除单个和多个
    redis.del({"key1", "key2"});
    res = redis.exists({"key1", "key2"});
    cout << res << endl;
}

// 测试 keys
void test_keys(redis::Redis &redis){
    cout << "test keys" << endl;
    // 先清空数据库
    redis.flushall();
    // 设置值
    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");

    // 使用迭代器解耦合
    std::vector<std::string> keys;
    auto ptr = std::back_insert_iterator(keys);
    redis.keys("*", ptr);
    printContainer(keys);
}

// 测试 expire 和 ttl
void test_expire_and_ttl(redis::Redis &redis){
    using namespace std::chrono_literals;   // 字面值常量，3ms 表示3毫秒，3s 表示 3s

    cout << "test expire and ttl" << endl;
    // 先清空数据库
    redis.flushall();
    // 设置值
    redis.set("key1", "111");
    // 设置过期时间
    redis.expire("key1", std::chrono::seconds(10));
    // 等待三秒获取过期时间
    std::this_thread::sleep_for(3s); // 字面值常量
    auto ttl = redis.ttl("key1");
    cout << "key1 的过期时间: " << ttl << endl;
}

// 测试 type
void test_type(redis::Redis &redis){
    cout << "test type" << endl;

    // 先清空数据库
    redis.flushall();
    // 设置值
    redis.set("key1", "111"); // string
    redis.lpush("key2", {"1", "2", "3"}); // list
    redis.hset("key3", "zhangsan", "xiamen"); // hash
    redis.sadd("key4", {"1", "2", "3"}); // set
    redis.zadd("key5", "zhangsan", 100); // zset

    // 获取类型
    auto type = redis.type("key1");
    cout << "key1 的类型: " << type << endl;
    type = redis.type("key2");
    cout << "key2 的类型: " << type << endl;
    type = redis.type("key3");
    cout << "key3 的类型: " << type << endl;
    type = redis.type("key4");
    cout << "key4 的类型: " << type << endl;
    type = redis.type("key5");
    cout << "key5 的类型: " << type << endl;
}

int main(){

    const string url = "tcp://666666@127.0.0.1:6379";
    redis::Redis redis(url);

    //test_get_and_set(redis);
    //test_exists_and_del(redis);
    //test_expire_and_ttl(redis);
    // test_keys(redis);
    test_type(redis);

    return 0;
}